﻿// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "dllmain.h"

// 导入CDR类型库，并对有冲突的符号进行重命名（添加 My 前缀）
#import "libid:95e23c91-bc5a-49f3-8cd1-1fc515597048" \
            rename("GetCommandLine", "MyGetCommandLine") \
			rename("CopyFile", "MyCopyFile") \
			rename("FindWindow", "MyFindWindow")

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
    return TRUE;
}

// 创建一个自己的插件类，取名为 HelloWorldPlugin，并继承自 VGCore 命名空间中的 IVGAppPlugin
class HelloWorldPlugin : public VGCore::IVGAppPlugin {
private:
    // 声明一个CorelDRAW应用程序变量，相当于VBA中的 Application 类
    VGCore::IVGApplication* corelApp;
    // 声明方法：当CorelDRAW启动时
    void onCorelAppStart();
    // 引用计数
    volatile ULONG m_ulRefCount;
    // 缓存值
    long m_lCookie;
public:
    // 这是构造函数
    HelloWorldPlugin();
public:
    // IVGAppPlugin 的 4 个方法
    STDMETHOD(raw_OnLoad)(VGCore::IVGApplication* Application);
    STDMETHOD(raw_StartSession)();
    STDMETHOD(raw_StopSession)();
    STDMETHOD(raw_OnUnload)();
public:
    // IDispatch 的 4 个方法
    STDMETHOD(GetTypeInfoCount)(UINT* pctinfo) { return E_NOTIMPL; }
    STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { return E_NOTIMPL; }
    STDMETHOD(GetIDsOfNames)(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) { return E_NOTIMPL; }
    STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr);
public:
    // IUnknown 的 3 个方法
    STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
    STDMETHOD_(ULONG, AddRef)(void) { return ++m_ulRefCount; }
    STDMETHOD_(ULONG, Release)(void) {
        ULONG ulCount = --m_ulRefCount;
        if (ulCount == 0) {
            delete this;
        }
        return ulCount;
    }
};

// 成员函数定义：构造函数
HelloWorldPlugin::HelloWorldPlugin() {
	// 初始化变量
	corelApp = NULL;
	m_lCookie = 0;
	m_ulRefCount = 1;
    //MessageBox(NULL, _bstr_t("欢迎使用我的 HelloWorld CPG插件"), _bstr_t("CDR插件技术网"), MB_OK);
}

STDMETHODIMP HelloWorldPlugin::QueryInterface(REFIID riid, void** ppvObject) {
	HRESULT hr = S_OK;
	m_ulRefCount++;
	if (riid == IID_IUnknown) {
		*ppvObject = (IUnknown*)this;
	}
	else if (riid == IID_IDispatch) {
		*ppvObject = (IDispatch*)this;
	}
	else if (riid == __uuidof(VGCore::IVGAppPlugin)) {
		*ppvObject = (VGCore::IVGAppPlugin*)this;
	}
	else {
		m_ulRefCount--;
		hr = E_NOINTERFACE;
	}
	return hr;
}

STDMETHODIMP HelloWorldPlugin::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) {
	switch (dispIdMember) {
	case 0x0012:
		// 执行CDR启动初始化方法
		onCorelAppStart();
		break;
	case 0x0015:
		// 设置工具栏的状态
		if (pDispParams != NULL && pDispParams->cArgs == 3) {
			// 取得工具栏命令，判断是否为指定的命令

			_bstr_t strCmd(pDispParams->rgvarg[2].bstrVal);
			if (strCmd == _bstr_t("BT1")) {
				// 这里指定工具栏永远可用，可以动态更改工具栏的启用或者禁用状态（动态，指的是判断当前CDR文档的一些条件，比如没选中任何图形，那就不启用工具栏）
				*pDispParams->rgvarg[1].pboolVal = VARIANT_TRUE;
			}
			//else if (strCmd == _bstr_t("BT2")) {
			//	*pDispParams->rgvarg[1].pboolVal = VARIANT_TRUE;
			//}
			// 这里还可以判断 strCmd 是否为其他的命令
		}
		break;
	case 0x0014:
		// 读取工具栏的命令
		if (pDispParams != NULL && pDispParams->cArgs == 1) {
			// 取得工具栏命令，判断是否为指定的命令
			_bstr_t strCmd(pDispParams->rgvarg[0].bstrVal);
			if (strCmd == _bstr_t("BT1")) {
				MessageBox(NULL, _bstr_t("单击了BT1按钮！"), _bstr_t("调试"), MB_OK);
			}
			//else if (strCmd == _bstr_t("BT2")){
			//	MessageBox(NULL, _bstr_t("单击了BT2按钮！"), _bstr_t("调试"), MB_OK);
			//}
		}
		break;
	default:
		//MessageBox(NULL, _bstr_t("into 111！") + pDispParams->rgvarg[2].bstrVal, _bstr_t("调试"), MB_OK);
		break;
	}
	return S_OK;
}

STDMETHODIMP HelloWorldPlugin::raw_OnLoad(VGCore::IVGApplication* Application) {
	// 当CDR加载时，此时获得了一个应用程序的实例，将其传递给 corelApp
	corelApp = Application;
	if (corelApp) {
		// 添加引用
		corelApp->AddRef();
	}
	//MessageBox(NULL, _bstr_t("CorelDRAW启动了"), _bstr_t("www.cdrvba.com"), MB_OK);
	return S_OK;
}

STDMETHODIMP HelloWorldPlugin::raw_StartSession() {
	try {
		//auto ctl = corelApp->FrameWork->CommandBars->Add(_bstr_t("插件"), (VGCore::cuiBarPosition)4, false);//没有工具栏，就添加一个
		//ctl->Visible = true;//设置工具栏可见
		VGCore::ICUICommandBarPtr ctl = corelApp->FrameWork->CommandBars->Item[_bstr_t("Standard")];//读取名字为"插件"的工具栏,首次启动因为不存在这个工具栏而抛出异常
		auto bt = ctl->Controls->AddCustomButton(VGCore::cdrCmdCategoryPlugins, _bstr_t("BT1"), 0, false);//在工具栏里添加按钮  //
		_bstr_t bstrPath(corelApp->Path + _bstr_t("Plugins64\\BT1.ico")); 
		bt->SetIcon2(bstrPath);
		bt->Visible = true;//设置工具栏里的按钮可见
		corelApp->AddPluginCommand(_bstr_t("BT1"), _bstr_t("按钮1"), _bstr_t("我是第一个按钮"));//关联插件
		m_lCookie = corelApp->AdviseEvents(this);
	}
	catch (_com_error& e) {
		MessageBox(NULL, e.Description(), _bstr_t("raw_StartSession 出错了"), MB_ICONSTOP);
	}
	return S_OK;
}

STDMETHODIMP HelloWorldPlugin::raw_StopSession() {
	try {
		corelApp->UnadviseEvents(m_lCookie);
		corelApp->FrameWork->CommandBars->Item[_bstr_t("Standard")]->Reset();
		//MessageBox(NULL, _bstr_t("CorelDRAW关闭会话"), _bstr_t("www.cdrvba.com"), MB_OK);
	}
	catch (_com_error& e) {
		MessageBox(NULL, e.Description(), _bstr_t("raw_StopSession 出错了"), MB_ICONSTOP);
	}
	return S_OK;
}

STDMETHODIMP HelloWorldPlugin::raw_OnUnload() {
	if (corelApp) {
		corelApp->Release();
		corelApp = NULL;
		//MessageBox(NULL, _bstr_t("CorelDRAW卸载了"), _bstr_t("www.cdrvba.com"), MB_OK);
	}
	return S_OK;
}

// 实现方法：当CorelDRAW启动时
void HelloWorldPlugin::onCorelAppStart() {
	try {
		// 设置CDR的启动模式为：启动后不做任何事
		corelApp->StartupMode = VGCore::cdrStartupDoNothing;
		// 弹出一个  HelloWorld 消息框
		//MessageBox(NULL, _bstr_t("hello world"), _bstr_t("www.cdrvba.com"), MB_OK);
		// 创建一个文档，并修改当前页的尺寸为400x400（由于未指定单位，所以这里单位是英寸）
		//VGCore::IVGDocument *doc = corelApp->CreateDocument();
		//doc->ActivePage->SetSize(400, 400);
	}
	catch (_com_error& e) {
		// 如果捕捉到异常，则使用消息框显示错误消息（e是一个异常对象）
		MessageBox(NULL, e.Description(), _bstr_t("onCorelAppStart 出错了"), MB_ICONSTOP);
	}
}

// 暴露AttachPlugin函数，这是CDR调用CPG插件的入口
extern "C" __declspec(dllexport) DWORD APIENTRY AttachPlugin(VGCore::IVGAppPlugin * *CorelDrawPlugin) {
	// 实例化插件，这里创建了一个CPG插件类的实例
	*CorelDrawPlugin = new HelloWorldPlugin;
    return 0x100;
}

